#include "tcs_struct_operator.h"
#include "tss_error.h"
#include "platform.h"
#include "indicate.h"

/* extern M_MSG_Head m_MSG_Head;*/

double getUrgency(M_MSG_Ask* tmpMsg);
TSS_RESULT tcs_mStruct_pack(IN MSG_Ask msgAsk, OUT M_MSG_Ask *p);


TSS_RESULT tcs_mStruct_init(M_MSG_Head * pm_MSG_Head) {
    TSS_RESULT res = TDDL_SUCCESS;
    if(pm_MSG_Head == NULL) {
        res = TDDL_NULL_POINTER;
    }

    pm_MSG_Head->tail = NULL;
    pm_MSG_Head->next = NULL;

    return res;
}

int tcs_mStruct_isNull(M_MSG_Head m_MSG_Head) {
    int res = 1;
    if(m_MSG_Head.next == NULL) {
        res = 0;
    }
    return res;
}

TSS_RESULT tcs_msgAsk_copy(MSG_Ask source, MSG_Ask *pDestination) {
    TSS_RESULT res = TDDL_SUCCESS;
    if(pDestination == NULL) {
        res = TDDL_NULL_POINTER;
    }
    else {
        pDestination->priority = source.priority;
        pDestination->trustAskSt = source.trustAskSt;
        pDestination->msgResponse = source.msgResponse;
    }
    return res;
}

TSS_RESULT tcs_mStruct_copy(M_MSG_Ask source, M_MSG_Ask *pDestination) {
    TSS_RESULT res = TDDL_SUCCESS;
    if(pDestination == NULL) {
        res = TDDL_NULL_POINTER;
    }
    else {
        pDestination->counts = source.counts;
        pDestination->priority = source.priority;
        pDestination->next = source.next;
        tcs_msgAsk_copy(source.msgAsk, &(pDestination->msgAsk));
    }
    return res;
}

TSS_RESULT tcs_mStruct_pack(IN MSG_Ask msgAsk, OUT M_MSG_Ask *p) {
    TSS_RESULT res = TDDL_SUCCESS;
    if(p == NULL) {
        res = TDDL_NULL_POINTER;
    }
    else {
        p->counts = 0;
        p->next = NULL;
        p->priority = msgAsk.priority;
        tcs_msgAsk_copy(msgAsk, &(p->msgAsk));
    }
    return res;
}

TSS_RESULT tcs_mStruct_append(IN MSG_Ask msgAsk, M_MSG_Head *pm_MSG_Head) {
    TSS_RESULT res = TDDL_SUCCESS;
    M_MSG_Ask* p;
	p = (M_MSG_Ask*) malloc (sizeof(M_MSG_Ask));
    if(p == NULL) {
        res = TDDL_ERROR_MALLOC;
    }
    else {
        if(pm_MSG_Head->next == NULL) {
            pm_MSG_Head->next = p;
            pm_MSG_Head->tail = p;
        }
        else {
            pm_MSG_Head->tail->next = p;
            pm_MSG_Head->tail = p;
        }
        res = tcs_mStruct_pack(msgAsk, p);
    }
    return res;
}

TSS_RESULT tcs_mStruct_getUrgentest(OUT MSG_Ask* pmsgAsk, M_MSG_Head * pm_MSG_Head) {
    TSS_RESULT res = TDDL_SUCCESS;
    M_MSG_Ask *tmpMsg, *maxUMsg, *prevTmpMsg, *prevMaxUMsg;
    double maxUrgency, tmpUrgency;

    tmpMsg = maxUMsg = pm_MSG_Head->next;
    prevMaxUMsg = prevTmpMsg = NULL;
    if(tmpMsg == NULL) {
        res = TDDL_NULL_QUEUE;
    }
    else {
        maxUrgency = tmpUrgency = getUrgency(tmpMsg);
        prevTmpMsg = tmpMsg;
        tmpMsg = tmpMsg->next;
        while(tmpMsg) {
            tmpUrgency = getUrgency(tmpMsg);
            if(tmpUrgency > maxUrgency) {
                maxUrgency = tmpUrgency;
                prevMaxUMsg = prevTmpMsg;
                maxUMsg = tmpMsg;
            }
            prevTmpMsg = tmpMsg;
            tmpMsg = tmpMsg->next;
        }
        tcs_msgAsk_copy(maxUMsg->msgAsk, pmsgAsk);
        /* maxUMsg 是队列里唯一节点*/
        if(prevTmpMsg == pm_MSG_Head->next) {
            pm_MSG_Head->tail = NULL;
            pm_MSG_Head->next = NULL;
        }
        /* 队列长度超过1，maxUMsg是队列头节点*/
        else if(prevMaxUMsg == NULL) {
            pm_MSG_Head->next = maxUMsg->next;
        }
        /* 队列长度超过1，maxUMsg是队列尾节点*/
        else if(maxUMsg->next == NULL){
            pm_MSG_Head->tail = prevMaxUMsg;
            prevMaxUMsg->next = NULL;
        }
        /* 队列长度超过2，maxUMsg是队列中非头节点也非尾节点*/
        else {
            prevMaxUMsg->next = maxUMsg->next;
        }
        free(maxUMsg);
        res = TDDL_SUCCESS;
    }
    return res;
}

/* 使用指针的原因：对每个节点，每次计算Urgency之后需将其counts加1*/
double getUrgency(M_MSG_Ask* tmpMsg) {
    double res = 0;
    res = tmpMsg->counts * 0.3 + tmpMsg->priority * 0.7;
    tmpMsg->counts++;
    return res;
}

void displayQ(M_MSG_Head m_MSG_Head) {
    M_MSG_Ask* p;
    p = m_MSG_Head.next;
    printf("\n------In My Queue.------\n");
    while (p != NULL) {
        printf("\tcounts = %d priority = %d\n", p->counts, p->priority);
        p = p->next;
    }
    printf("------In My Queue.------\n");
}
